package org.cybzacg.convert.utils;

import org.cybzacg.convert.annotation.CopyProperty;

import java.lang.annotation.Annotation;
import java.lang.reflect.*;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 反射工具类
 * 封装常用的反射操作，提供字段访问权限管理和缓存机制
 * 
 * @author PropertyCopier Implementation
 * @version 1.0.0
 */
public class ReflectionUtils {
    
    // 缓存字段信息，提升反射性能
    private static final Map<Class<?>, List<Field>> FIELD_CACHE = new ConcurrentHashMap<>();
    private static final Map<Class<?>, Map<String, Field>> FIELD_MAP_CACHE = new ConcurrentHashMap<>();
    private static final Map<Field, Method> GETTER_CACHE = new ConcurrentHashMap<>();
    private static final Map<Field, Method> SETTER_CACHE = new ConcurrentHashMap<>();
    private static final Map<Class<?>, Constructor<?>> CONSTRUCTOR_CACHE = new ConcurrentHashMap<>();
    
    // 基本类型对应的包装类型映射
    private static final Map<Class<?>, Class<?>> PRIMITIVE_TO_WRAPPER = new HashMap<>();
    private static final Map<Class<?>, Class<?>> WRAPPER_TO_PRIMITIVE = new HashMap<>();
    
    static {
        // 初始化基本类型和包装类型的映射
        PRIMITIVE_TO_WRAPPER.put(boolean.class, Boolean.class);
        PRIMITIVE_TO_WRAPPER.put(byte.class, Byte.class);
        PRIMITIVE_TO_WRAPPER.put(char.class, Character.class);
        PRIMITIVE_TO_WRAPPER.put(short.class, Short.class);
        PRIMITIVE_TO_WRAPPER.put(int.class, Integer.class);
        PRIMITIVE_TO_WRAPPER.put(long.class, Long.class);
        PRIMITIVE_TO_WRAPPER.put(float.class, Float.class);
        PRIMITIVE_TO_WRAPPER.put(double.class, Double.class);
        PRIMITIVE_TO_WRAPPER.put(void.class, Void.class);
        
        for (Map.Entry<Class<?>, Class<?>> entry : PRIMITIVE_TO_WRAPPER.entrySet()) {
            WRAPPER_TO_PRIMITIVE.put(entry.getValue(), entry.getKey());
        }
    }
    
    /**
     * 获取类的所有字段（包括继承的字段）
     * 
     * @param clazz 目标类
     * @return 所有字段的列表
     */
    public static List<Field> getAllFields(Class<?> clazz) {
        if (clazz == null) {
            return Collections.emptyList();
        }
        
        return FIELD_CACHE.computeIfAbsent(clazz, ReflectionUtils::doGetAllFields);
    }
    
    /**
     * 递归获取所有字段的实际实现
     */
    private static List<Field> doGetAllFields(Class<?> clazz) {
        List<Field> fields = new ArrayList<>();
        Class<?> currentClass = clazz;
        
        while (currentClass != null && currentClass != Object.class) {
            Field[] declaredFields = currentClass.getDeclaredFields();
            for (Field field : declaredFields) {
                // 过滤掉静态字段和编译器生成的字段
                if (!Modifier.isStatic(field.getModifiers()) && 
                    !field.isSynthetic() && 
                    !field.getName().startsWith("this$")) {
                    fields.add(field);
                }
            }
            currentClass = currentClass.getSuperclass();
        }
        
        return fields;
    }
    
    /**
     * 根据字段名获取字段
     * 
     * @param clazz 目标类
     * @param fieldName 字段名
     * @return 字段对象，如果未找到则返回null
     */
    public static Field getField(Class<?> clazz, String fieldName) {
        if (clazz == null || fieldName == null || fieldName.trim().isEmpty()) {
            return null;
        }
        
        Map<String, Field> fieldMap = FIELD_MAP_CACHE.computeIfAbsent(clazz, 
            cls -> {
                Map<String, Field> map = new HashMap<>();
                for (Field field : getAllFields(cls)) {
                    map.put(field.getName(), field);
                }
                return map;
            });
        
        return fieldMap.get(fieldName);
    }
    
    /**
     * 检查字段是否可读
     * 
     * @param field 字段对象
     * @return 如果字段可读则返回true
     */
    public static boolean isReadable(Field field) {
        if (field == null) {
            return false;
        }
        
        // 检查是否有getter方法
        Method getter = findGetterMethod(field);
        if (getter != null) {
            return true;
        }
        
        // 检查字段访问权限
        return !Modifier.isFinal(field.getModifiers());
    }
    
    /**
     * 检查字段是否可写
     * 
     * @param field 字段对象
     * @return 如果字段可写则返回true
     */
    public static boolean isWritable(Field field) {
        if (field == null) {
            return false;
        }
        
        // 检查是否有setter方法
        Method setter = findSetterMethod(field);
        if (setter != null) {
            return true;
        }
        
        // 检查字段访问权限
        return !Modifier.isFinal(field.getModifiers());
    }
    
    /**
     * 获取字段值
     * 
     * @param field 字段对象
     * @param target 目标对象
     * @return 字段值
     * @throws ReflectionException 反射操作异常
     */
    public static Object getFieldValue(Field field, Object target) throws ReflectionException {
        if (field == null || target == null) {
            return null;
        }
        
        try {
            // 优先使用getter方法
            Method getter = findGetterMethod(field);
            if (getter != null) {
                return getter.invoke(target);
            }
            
            // 直接访问字段
            makeAccessible(field);
            return field.get(target);
        } catch (Exception e) {
            throw new ReflectionException("无法获取字段值: " + field.getName(), e);
        }
    }
    
    /**
     * 设置字段值
     * 
     * @param field 字段对象
     * @param target 目标对象
     * @param value 要设置的值
     * @throws ReflectionException 反射操作异常
     */
    public static void setFieldValue(Field field, Object target, Object value) throws ReflectionException {
        if (field == null || target == null) {
            return;
        }
        
        try {
            // 优先使用setter方法
            Method setter = findSetterMethod(field);
            if (setter != null) {
                setter.invoke(target, value);
                return;
            }
            
            // 直接设置字段值
            makeAccessible(field);
            field.set(target, value);
        } catch (Exception e) {
            throw new ReflectionException("无法设置字段值: " + field.getName(), e);
        }
    }
    
    /**
     * 查找getter方法
     * 
     * @param field 字段对象
     * @return getter方法，如果未找到则返回null
     */
    public static Method findGetterMethod(Field field) {
        if (field == null) {
            return null;
        }
        
        return GETTER_CACHE.computeIfAbsent(field, f -> {
            Class<?> clazz = f.getDeclaringClass();
            String fieldName = f.getName();
            Class<?> fieldType = f.getType();
            
            // 尝试 getXxx() 方法
            String getterName = "get" + capitalize(fieldName);
            try {
                Method method = clazz.getMethod(getterName);
                if (method.getReturnType() == fieldType) {
                    return method;
                }
            } catch (NoSuchMethodException e) {
                // 忽略，继续尝试其他方法
            }
            
            // 尝试 isXxx() 方法（仅用于boolean类型）
            if (fieldType == boolean.class || fieldType == Boolean.class) {
                String isName = "is" + capitalize(fieldName);
                try {
                    Method method = clazz.getMethod(isName);
                    if (method.getReturnType() == boolean.class || method.getReturnType() == Boolean.class) {
                        return method;
                    }
                } catch (NoSuchMethodException e) {
                    // 忽略
                }
            }
            
            return null;
        });
    }
    
    /**
     * 查找setter方法
     * 
     * @param field 字段对象
     * @return setter方法，如果未找到则返回null
     */
    public static Method findSetterMethod(Field field) {
        if (field == null) {
            return null;
        }
        
        return SETTER_CACHE.computeIfAbsent(field, f -> {
            Class<?> clazz = f.getDeclaringClass();
            String fieldName = f.getName();
            Class<?> fieldType = f.getType();
            
            String setterName = "set" + capitalize(fieldName);
            try {
                return clazz.getMethod(setterName, fieldType);
            } catch (NoSuchMethodException e) {
                // 忽略
            }
            
            return null;
        });
    }
    
    /**
     * 创建类的实例
     * 
     * @param clazz 目标类
     * @return 新创建的实例
     * @throws ReflectionException 反射操作异常
     */
    public static <T> T createInstance(Class<T> clazz) throws ReflectionException {
        if (clazz == null) {
            return null;
        }
        
        try {
            Constructor<T> constructor = getDefaultConstructor(clazz);
            if (constructor != null) {
                return constructor.newInstance();
            }
            
            throw new ReflectionException("无法找到默认构造函数: " + clazz.getName());
        } catch (Exception e) {
            throw new ReflectionException("无法创建实例: " + clazz.getName(), e);
        }
    }
    
    /**
     * 获取默认构造函数
     * 
     * @param clazz 目标类
     * @return 默认构造函数，如果未找到则返回null
     */
    @SuppressWarnings("unchecked")
    public static <T> Constructor<T> getDefaultConstructor(Class<T> clazz) {
        if (clazz == null) {
            return null;
        }
        
        return (Constructor<T>) CONSTRUCTOR_CACHE.computeIfAbsent(clazz, cls -> {
            try {
                Constructor<?> constructor = cls.getDeclaredConstructor();
                makeAccessible(constructor);
                return constructor;
            } catch (NoSuchMethodException e) {
                return null;
            }
        });
    }
    
    /**
     * 检查类型是否兼容
     * 
     * @param sourceType 源类型
     * @param targetType 目标类型
     * @return 如果类型兼容则返回true
     */
    public static boolean isTypeCompatible(Class<?> sourceType, Class<?> targetType) {
        if (sourceType == null || targetType == null) {
            return false;
        }
        
        // 相同类型
        if (sourceType.equals(targetType)) {
            return true;
        }
        
        // 基本类型和包装类型的兼容性
        Class<?> sourceWrapper = PRIMITIVE_TO_WRAPPER.getOrDefault(sourceType, sourceType);
        Class<?> targetWrapper = PRIMITIVE_TO_WRAPPER.getOrDefault(targetType, targetType);
        
        if (sourceWrapper.equals(targetWrapper)) {
            return true;
        }
        
        // 检查继承关系
        return targetType.isAssignableFrom(sourceType);
    }
    
    /**
     * 获取字段的CopyProperty注解
     * 
     * @param field 字段对象
     * @return CopyProperty注解，如果不存在则返回null
     */
    public static CopyProperty getCopyPropertyAnnotation(Field field) {
        if (field == null) {
            return null;
        }
        
        return field.getAnnotation(CopyProperty.class);
    }
    
    /**
     * 获取类的CopyProperty注解
     * 
     * @param clazz 目标类
     * @return CopyProperty注解，如果不存在则返回null
     */
    public static CopyProperty getCopyPropertyAnnotation(Class<?> clazz) {
        if (clazz == null) {
            return null;
        }
        
        return clazz.getAnnotation(CopyProperty.class);
    }
    
    /**
     * 检查字段是否有指定注解
     * 
     * @param field 字段对象
     * @param annotationClass 注解类型
     * @return 如果有指定注解则返回true
     */
    public static boolean hasAnnotation(Field field, Class<? extends Annotation> annotationClass) {
        if (field == null || annotationClass == null) {
            return false;
        }
        
        return field.getAnnotation(annotationClass) != null;
    }
    
    /**
     * 检查类是否有指定注解
     * 
     * @param clazz 目标类
     * @param annotationClass 注解类型
     * @return 如果有指定注解则返回true
     */
    public static boolean hasAnnotation(Class<?> clazz, Class<? extends Annotation> annotationClass) {
        if (clazz == null || annotationClass == null) {
            return false;
        }
        
        return clazz.getAnnotation(annotationClass) != null;
    }
    
    /**
     * 使字段可访问
     * 
     * @param field 字段对象
     */
    public static void makeAccessible(Field field) {
        if (field != null && !Modifier.isPublic(field.getModifiers())) {
            field.setAccessible(true);
        }
    }
    
    /**
     * 使构造函数可访问
     * 
     * @param constructor 构造函数对象
     */
    public static void makeAccessible(Constructor<?> constructor) {
        if (constructor != null && !Modifier.isPublic(constructor.getModifiers())) {
            constructor.setAccessible(true);
        }
    }
    
    /**
     * 使方法可访问
     * 
     * @param method 方法对象
     */
    public static void makeAccessible(Method method) {
        if (method != null && !Modifier.isPublic(method.getModifiers())) {
            method.setAccessible(true);
        }
    }
    
    /**
     * 首字母大写
     * 
     * @param str 字符串
     * @return 首字母大写的字符串
     */
    private static String capitalize(String str) {
        if (str == null || str.isEmpty()) {
            return str;
        }
        return str.substring(0, 1).toUpperCase() + str.substring(1);
    }
    
    /**
     * 清除缓存
     */
    public static void clearCache() {
        FIELD_CACHE.clear();
        FIELD_MAP_CACHE.clear();
        GETTER_CACHE.clear();
        SETTER_CACHE.clear();
        CONSTRUCTOR_CACHE.clear();
    }
    
    /**
     * 获取缓存统计信息
     * 
     * @return 缓存统计信息
     */
    public static Map<String, Integer> getCacheStatistics() {
        Map<String, Integer> stats = new HashMap<>();
        stats.put("fieldCache", FIELD_CACHE.size());
        stats.put("fieldMapCache", FIELD_MAP_CACHE.size());
        stats.put("getterCache", GETTER_CACHE.size());
        stats.put("setterCache", SETTER_CACHE.size());
        stats.put("constructorCache", CONSTRUCTOR_CACHE.size());
        return stats;
    }
    
    /**
     * 反射操作异常类
     */
    public static class ReflectionException extends Exception {
        public ReflectionException(String message) {
            super(message);
        }
        
        public ReflectionException(String message, Throwable cause) {
            super(message, cause);
        }
    }
}
